<?php


namespace App\Crontab;


use App\Model\CacheTable;
use App\Model\DataTable;
use App\Model\User;
use App\Model\Wechat;
use App\Utility\FinanceUtil;
use App\Utility\Pool\MysqlPool;
use App\Utility\Pool\RedisPool;
use App\Utility\Queue\Queue;
use App\Utility\Queue\QueueType;
use EasySwoole\EasySwoole\Crontab\AbstractCronTask;
use EasySwoole\EasySwoole\Task\TaskManager;
use EasySwoole\Queue\Job;
use EasySwoole\Utility\File;
use EasySwoole\WeChat\Bean\OfficialAccount\TemplateMsg;

class GuessTask extends AbstractCronTask
{

    private static $FIELD = 'u.openname,u.openid,s.score';
    private static $FIELD_FAIL = 'u.openname,u.openid';


    public static function getRule(): string
    {
        // TODO: Implement getRule() method.
        return '2 15 * * *';
    }

    public static function getTaskName(): string
    {
        // TODO: Implement getTaskName() method.
        return 'GuessTask';
    }


    function run(int $taskId, int $workerIndex)
    {
        // TODO: Implement run() method.
        echo('send' . self::getTaskName() . PHP_EOL);
        TaskManager::getInstance()->async(function () {
            GuessTask::mytask();
        });

    }

    function onException(\Throwable $throwable, int $taskId, int $workerIndex)
    {
        // TODO: Implement onException() method.
        echo $throwable->getMessage();
    }


    public static function mytask()
    {
        $redis = RedisPool::defer();
        //$key = 'cz_tradeday';
        //$data['last'] = FinanceUtil::lastTradeDayTime();
        //$data['next'] = FinanceUtil::nextTradeDayTime();
        //$redis->set($key,json_encode($data),3600);

        $week = date("w");

        if ($week == 0) {
            //全部战绩清0
            $db = MysqlPool::defer();
            $updateGuessScore['wintime'] = 0;
            $updateGuessScore['bestwin'] = 0;
            $updateGuessScore['wincount'] = 0;
            $updateGuessScore['tjtime'] = 0;
            $updateGuessScore['time'] = 0;
            $db->update(DataTable::FINANCE_SCORE_TABLE, $updateGuessScore);
        }

        //特殊日子
        if (!in_array($week, [0, 6])) {
            $date_str = date('Ymd');
            $dataKline = json_decode(file_get_contents('http://img1.money.126.net/data/hs/time/today/0000001.json'));
            if ($date_str == $dataKline->date) {
                $count = count($dataKline->data);
                //$count = 242;
                if ($count == 242) {
                    $yestclose = $dataKline->yestclose;
                    $todayclose = ($dataKline->data)[241][1];
                    //$todayclose = ($dataKline->data)[count($dataKline->data)-1][1];
                    if ($todayclose == $yestclose) {
                        self::tjpin();

                    } else if ($todayclose > $yestclose) {
                        //涨
                        self::tj(1);
                    } else {
                        //跌
                        self::tj(0);

                    }
                }
            }
        }
        //星期五，更新排行榜了喂
        if ($week == 5) {
            //
            $wincount = 5;

            $date_str = date('Ymd');
            if ($date_str == '20190913') {
                $wincount = 4;
            } else if ($date_str == '20191004') {
                $wincount = 1;
            } else if ($date_str == '20191011') {
                $wincount = 4;
            }
            $db = MysqlPool::defer();

            //就是拿两人
            $userlist = $db
                ->where('s.bestwin', $wincount)
                ->join(DataTable::USER_TABLE . ' as u', 'u.id = s.user_id')
                ->orderBy('s.bestwin')
                ->get(DataTable::FINANCE_SCORE_TABLE . ' as s ', null, 'u.id,u.nickname,u.avatar,s.bestwin');
            shuffle($userlist);
            $templist = array();
            if (count($userlist) > 4) {
                $tempcount = 3;
            } else {
                $tempcount = count($userlist);
            }


            $count = 5 - $tempcount;

            //自己的三人
            $robot = $db->get(DataTable::GUESS_ROBOT_TABLE, $count);

            foreach ($robot as $r) {
                $r['bestwin'] = $wincount;
                array_push($templist, $r);
            }
            if ($count != 5) {
                for ($i = 0; $i < $tempcount; $i++) {
                    array_push($templist, $userlist[$i]);
                }
            }

            shuffle($templist);
            //生成文档
            File::createFile(EASYSWOOLE_TEMP_DIR . '/score.data', json_encode($templist), true);
            //设置缓存
            $key = 'cz_score_best_winer_list';
            $redis->set($key, json_encode($templist), 604800);
        }
    }


    private static function tj($falg)
    {
        //如果胜者为1 即涨为胜，跌为输
        //如果胜者为0 即涨为输，跌为胜
        $tempbasescore = 200;

        //$begtime = FinanceUtil::now2h15guess();
        //$endtime = FinanceUtil::today9hour();
        $date_str = date('Ymd');
        $db = MysqlPool::defer();
        //判断今天是否结算过了
        $count = $db->where('status', '竞猜中')
            //->whereBetween('createtime',[$begtime,$endtime])//废弃
            ->where('date_str', $date_str)
            ->count(DataTable::GUESS_TABLE);
        if ($count < 1) {
            return true;
        }

        //查询胜者的人数
        $wincount = $db->where('beat', $falg)
            //->whereBetween('createtime',[$begtime,$endtime])
            ->where('status', '竞猜中')
            ->where('date_str', $date_str)
            ->count(DataTable::GUESS_TABLE);
        //查询败者总分数
        $total_score = $db->where('beat', $falg, '!=')
            //->whereBetween('createtime',[$begtime,$endtime])
            ->where('status', '竞猜中')
            ->where('date_str', $date_str)
            ->sum(DataTable::GUESS_TABLE, 'score');
        /*
        if($total_score < 5000){
            $total_score += 3000;
        }else if($total_score < 50000){
            $total_score += 20000;
        }else if($total_score < 100000){
            $total_score += 50000;
        }*/
        if ($total_score < $wincount) {
            $total_score = $wincount;
        }

        $basescore = (int)($total_score / $wincount) + 100;
        if ($basescore >= $tempbasescore) {
            $basescore = $tempbasescore + rand(-30, 40);
        }

        //$basescore = 250 + rand(-50,50);
        //如果统计人数大于1000人次，分段统计
        //去掉已经统计的
        $page_size = QueueType::MESSAGE_GUESS_COUNT;
        $tempcount = $db->where('beat', $falg)
            ->where('status', '竞猜中')
            ->where('date_str', $date_str)
            //->whereBetween('createtime',[$begtime,$endtime])
            ->count(DataTable::GUESS_TABLE);
        $pages = intval($tempcount / $page_size);
        if ($pages < 1) {
            if ($tempcount > 0) {
                self::updateScore($tempcount, $falg, $basescore, $date_str);
            }
        } else {

            for ($page = 0; $page < $pages - 1; $page++) {
                self::updateScore([$page * $page_size, $page_size], $falg, $basescore, $date_str);
            }
            //取余数
            $mod = $tempcount % $page_size;
            if ($mod > 0) {
                self::updateScore([$tempcount - $mod, $mod], $falg, $basescore, $date_str);
            }
        }
        //更新失败者
        //更新状态
        $guessobj['updatetime'] = time();
        $guessobj['status'] = '未中奖';
        $db->where('beat', $falg, '!=')
            ->where('date_str', $date_str)
            //->whereBetween('createtime',[$begtime,$endtime])
            ->where('status', '竞猜中')
            ->update(DataTable::GUESS_TABLE, $guessobj);
        //今天失败的连胜中断
        $db->where('createtime', time() - 7200, '<')
            ->setInc(DataTable::FINANCE_SCORE_TABLE, 'tjtime');
        $financeobj['wintime'] = 0;
        $financeobj['createtime'] = time();
        $db->where('createtime', time() - 7200, '<')
            ->update(DataTable::FINANCE_SCORE_TABLE, $financeobj);


    }


    private static function updateScore($limit, $falg, $basescore, $date_str)
    {
        //更新胜者
        $db = MysqlPool::defer();
        $db->startTransaction();
        try {
            $list = $db->where('beat', $falg, '=')
                //->whereBetween('createtime',$time_key)
                ->where('date_str', $date_str)
                ->where('status', '竞猜中', '=')
                ->get(DataTable::GUESS_TABLE, $limit, 'user_id');
            $templist = array();
            foreach ($list as $u) {
                //取这个号的信息
                User::score($db, $basescore, $u['user_id'], '竞猜获得积分奖励');
                //判断连胜
                $finance_score = $db->where('user_id', $u['user_id'], '=')
                    ->getOne(DataTable::FINANCE_SCORE_TABLE);
                if ($finance_score) {
                    if ($finance_score['createtime'] >= (FinanceUtil::today15hour() - 90000)) {
                        //连胜
                        $updataFinance['wintime'] = $finance_score['wintime'] + 1;
                        $updataFinance['bestwin'] = max($updataFinance['wintime'], $finance_score['bestwin']);

                    } else {
                        $updataFinance['wintime'] = 1;
                    }
                    $updataFinance['createtime'] = time();
                    $updataFinance['tjtime'] = $finance_score['tjtime'] + 1;
                    $updataFinance['wincount'] = $finance_score['wincount'] + 1;
                    if ($finance_score['time'] == 0) {
                        $finance_score['time'] = 1;
                    }

                    //更新
                    $db->where('user_id', $u['user_id'])
                        ->update(DataTable::FINANCE_SCORE_TABLE, $updataFinance);
                } else {
                    //插入
                    $insterFinance['user_id'] = $u['user_id'];
                    $insterFinance['wintime'] = 1;
                    $insterFinance['bestwin'] = 1;
                    $insterFinance['createtime'] = time();
                    $insterFinance['wincount'] = 1;
                    $insterFinance['time'] = 1;
                    $insterFinance['tjtime'] = 1;
                    $db->insert(DataTable::FINANCE_SCORE_TABLE, $insterFinance);
                }
                array_push($templist, $u['user_id']);

            }
            //更新状态
            $guessobj['status'] = '已中奖';
            $guessobj['updatetime'] = time();
            $db->where('beat', $falg, '=')
                //->whereBetween('createtime',$time_key)
                ->where('date_str', $date_str)
                ->whereIn('user_id', $templist)
                ->where('status', '竞猜中', '=')
                ->update(DataTable::GUESS_TABLE, $guessobj);
            $db->commit();
        } catch (\Exception $e) {
            $db->rollback();
        }


    }

    //返回平手积分
    private static function tjpin()
    {
        //$begtime = FinanceUtil::now2h15guess();
        //$endtime = FinanceUtil::today9hour();
        $db = MysqlPool::defer();
        $date_str = date('Ymd');
        $tempcount = $db->where('status', '竞猜中')
            ->where('date_str', $date_str)
            //->whereBetween('createtime',[$begtime,$endtime])
            ->count(DataTable::GUESS_TABLE);
        $page_size = QueueType::MESSAGE_GUESS_COUNT;
        $pages = intval($tempcount / $page_size);
        if ($pages < 1) {
            if ($tempcount > 0) {
                self::updateScorePin($tempcount, $date_str);
            }
        } else {

            for ($page = 0; $page < $pages - 1; $page++) {
                self::updateScorePin([$page * $page_size, $page_size], $date_str);
            }
            //取余数
            $mod = $tempcount % $page_size;
            if ($mod > 0) {
                self::updateScorePin([$tempcount - $mod, $mod], $date_str);
            }
        }
    }

    private static function updateScorePin($limit, $date_str)
    {

        $basescore = 100;
        //更新胜者
        $db = MysqlPool::defer();
        $db->startTransaction();
        try {
            $list = $db
                //->whereBetween('createtime',$timekey)
                ->where('date_str', $date_str)
                ->where('status', '竞猜中', '=')
                ->get(DataTable::GUESS_TABLE, $limit, 'user_id');
            $templist = array();
            foreach ($list as $u) {
                //取这个号的信息
                User::score($db, $basescore, $u['user_id'], '竞猜返还积分');
                array_push($templist, $u['user_id']);
            }

            //更新状态
            $guessobj['status'] = '未中奖';
            $guessobj['updatetime'] = time();
            $db->where('date_str', $date_str)
                //->whereBetween('createtime',$timekey)
                ->whereIn('user_id', $templist)
                ->where('status', '竞猜中', '=')
                ->update(DataTable::GUESS_TABLE, $guessobj);
            //连胜中断

            $db->where('createtime', time() - 7200, '<')
                ->setInc(DataTable::FINANCE_SCORE_TABLE, 'tjtime');
            $financeobj['wintime'] = 0;
            $financeobj['createtime'] = time();
            $db->where('createtime', time() - 7200, '<')
                ->update(DataTable::FINANCE_SCORE_TABLE, $financeobj);
            $db->commit();
        } catch (\Exception $e) {
            $db->rollback();
        }
    }


    public static function sendMsg()
    {
        //除周六周日
        $week = date("w");
        if (!in_array($week, [0, 6])) {
            $db = MysqlPool::defer();
            //猜中的
            $status_key = '竞猜获得积分奖励';
            $date_str = date("Ymd");
            $page_size = QueueType::MESSAGE_SEND_COUNT;

            $count = $db->where('date_str', $date_str)
                ->where('memo', $status_key)
                ->count(DataTable::SCORE_LOG_TABLE);
            $pages = (int)$count / $page_size;
            if ($pages < 1) {
                if ($count > 0) {
                    self::querydata_success($db, $status_key, $count);
                }
            } else {
                for ($page = 0; $page < $pages - 1; $page++) {
                    self::querydata_success($db, $status_key, [$page * $page_size, $page_size]);
                }
                //取余数
                $mod = $count % $page_size;
                if ($mod > 0) {
                    self::querydata_success($db, $status_key, [$count - $mod, $mod]);
                }
            }
            //没猜中的
            $count = $db->where('status', '未中奖', '=')
                ->where('date_str', $date_str)
                ->count(DataTable::GUESS_TABLE);
            $pages = (int)$count / $page_size;
            if ($pages < 1) {
                if ($count > 0) {
                    self::querydata_fail($db, $date_str, $count);
                }
            } else {
                for ($page = 0; $page < $pages - 1; $page++) {
                    self::querydata_fail($db, $date_str, [$page * $page_size, $page_size]);
                }
                //取余数
                $mod = $count % $page_size;
                if ($mod > 0) {
                    self::querydata_fail($db, $date_str, [$count - $mod, $mod]);
                }
            }
        }
    }


    private static function querydata_success($db, $status_key, $limit)
    {
        $date_str = date("Ymd");
        $list = $db
            ->join(DataTable::THIRD_TABLE . ' as u', 'u.user_id = s.user_id')
            ->join(DataTable::USER_TABLE . ' as t', 't.id = s.user_id')
            ->where('s.date_str', $date_str)
            ->where('s.memo', $status_key)
            ->where('u.is_follow', 1)
            ->where('t.status', 'normal')
            ->get(DataTable::SCORE_LOG_TABLE . ' as s', $limit, self::$FIELD);
        //添加一个JOB
        self::SetJob($list, QueueType::MESSAGE_GUESS_SUCCESS);
    }


    private static function querydata_fail($db, $date_str, $limit)
    {
        $list = $db
            ->join(DataTable::THIRD_TABLE . ' as u', 'u.user_id = g.user_id')
            ->join(DataTable::USER_TABLE . ' as t', 't.id = g.user_id')
            ->where('g.date_str', $date_str)
            ->where('g.status', '未中奖')
            ->where('u.is_follow', 1)
            ->where('t.status', 'normal')
            ->get(DataTable::GUESS_TABLE . ' as g', $limit, self::$FIELD_FAIL);
        //添加一个JOB
        self::SetJob($list, QueueType::MESSAGE_GUESS_FAIL);

    }

    /**
     * @param $db
     * @param $ubeg 用户开始
     * @param $uend 用户结束
     */
    private static function setJob($list, $type)
    {
        if (count($list) > 0) {
            echo('发送类型' . $type . ':' . count($list) . '条' . PHP_EOL);
            $job = new Job();
            $data['list'] = $list;
            $data['type'] = $type;
            $job->setJobData($data);
            Queue::getInstance()->producer()->push($job);
        }
    }


    //成功的
    public static function consumer_success($list)
    {
        $wechat = new Wechat();
        $client = $wechat->GetClient();
        $date_str = date("Y-m-d");
        foreach ($list as $msg) {
            $data['first']['value'] = '尊敬的' . $msg['openname'] . '，你的预测结果正确，已获积分奖励！';
            $data['keyword1']['value'] = "大盘猜涨跌活动";
            $data['keyword2']['value'] = $msg['score'] . '积分已到账';
            $data['keyword3']['value'] = $date_str;
            $data['keyword4']['value'] = $date_str;
            $data['remark']['value'] = '感谢你的参与，可点击此处，立即兑换现金红包等奖励。';
            $tempmsg = new TemplateMsg();
            $tempmsg->setTemplateId('2DCx8HXOl5QTI6O8iJ-pk7g368iBcf6ztJwLeMwDlHM');
            $tempmsg->setTouser($msg['openid']);
            $tempmsg->setData($data);
            $tempmsg->setUrl(CacheTable::getFinanceConfig()['PAY_URL']);
            try {
                $client->officialAccount()->templateMsg()->send($tempmsg);
            } catch (\Exception $e) {
                continue;
            }
        }

    }

    //失败的
    public static function consumer_fail($list)
    {
        $wechat = new Wechat();
        $client = $wechat->GetClient();
        $date_str = date("Y-m-d");
        foreach ($list as $msg) {
            $data['first']['value'] = '尊敬的' . $msg['openname'] . '，你参与的大盘猜涨跌活动结果错误，未能获得奖励';
            $data['keyword1']['value'] = $date_str;
            $data['keyword2']['value'] = "预测结果与最终结果有差异，但仍有机会，希望下次获胜的就是你";
            $data['remark']['value'] = '感谢你的参与，如有问题可私信留言，联系客服。';
            $tempmsg = new TemplateMsg();
            $tempmsg->setTemplateId('6x4SL-c-cEjt4RW4rcTRuo1DmN67X0nnVGA15O8eA1k');
            $tempmsg->setTouser($msg['openid']);
            $tempmsg->setData($data);
            $tempmsg->setUrl(CacheTable::getFinanceConfig()['HOST_URL']);
            try {
                $client->officialAccount()->templateMsg()->send($tempmsg);
            } catch (\Exception $e) {
                continue;
            }
        }
    }


}